Add CODEOWNERS file to repo with GitHub Rest API and PowerShell

Dave Lloyd
ObjectSharp (a Centrilogic Company)
3 min readJul 20, 2022

--

I recently wrote a short article on creating a GitHub repo with Powershell and the GitHub Rest API. I thought I would add to that today.

If you are using the rest API to create repos you may want to add a CODEOWNERS file to make a particular team responsible for PR approvals on that repo. If you’re not familiar with the use of the CODEOWNERS file read this first.

You could add the CODEOWNERS file to a template and create the repo using a template, however you would still need to edit that CODEOWNERS file to specify who owns the code.

Here is a PowerShell script that will add the CODEOWNERS file with a team already to go.

For my example I’ll create a Powershell script called addCodeOwners.ps1 with:

  • Two parameters: The name of the repo and the team that will own the code.
  • A variable with the GitHub organization name. This could also be a parameter obviously.
  • A variable with the Personal Access Token we will get from an environment variable, converted to base64.
  • A Variable containing the path and file name of the CODEOWNERS file.
param (
[Parameter(Mandatory=$true)] $repoName,
[Parameter(Mandatory=$true)] $teamName)
$orgName = "myOrg"
$pat = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($env:GH_PAT)"))
$file = ".github/CODEOWNERS"

For the body of the Rest API call, we need to include a message and the file content for the commit. There are more parameters you can pass in via the body. They are either not required or will default to some value, see the Documentation for the other options. For example: If you don’t include the branch in the body, this call will use the default branch of the repo.

The content must be base64, and since the team name is the team slug it must be lowercase.

$teamName=$teamName.ToLower()
$content= "* @$orgName/$teamName"
$b64Content = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($content)"))
$body = @{message="Added CODEOWNERS to Repo"
content=$b64Content}

We are using the simplest syntax in our CODEOWNERS file to grant ownership to a team. In our script it will result in this line.

*   @MyOrg/developers
  • The asterisk refers to everything in the repo.
  • The team name must be is “@orgName/teamSlug”

You can specify specific file types or folders, check out these CODEOWNERS examples.

Now lets set up the call to Invoke-RestMethod.

$params = @{'Uri' = ('https://api.github.com/repos/{0}/{1}/contents/{2}' -f $orgName, $repoName,$file)
'Headers' = @{'Authorization' = 'Basic ' + $pat}
'Method' = 'Put'
'ContentType' = 'application/json'
'Body' = ($body | ConvertTo-Json)}
Invoke-RestMethod @params

The API call looks like this:

repos/<Owner>/<Repo>/contents/<Path>

  • Owner — which in our case is the name of the organization
  • Repo — The name of the Repo we want to add the CODEOWNERS file to
  • Path — the path and filename to add

Here is the whole script:

param (
[Parameter(Mandatory=$true)] $repoName,
[Parameter(Mandatory=$true)] $teamName)
$orgName = "myOrg"
$pat = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($env:GH_PAT)"))
$file = ".github/CODEOWNERS"
$teamName=$teamName.ToLower()
$content= "* @PartsUnlimited1/$teamName"
$b64Content = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($content)"))
$body = @{message="Added CODEOWNERS to Repo"
content=$b64Content}
$params = @{'Uri' = ('https://api.github.com/repos/{0}/{1}/contents/{2}' -f $orgName, $repoName,$file)
'Headers' = @{'Authorization' = 'Basic ' + $pat}
'Method' = 'Put'
'ContentType' = 'application/json'
'Body' = ($body | ConvertTo-Json)}
Invoke-RestMethod @params

Now just make the call to add CODEOWNERS to the repo with the team already defined.

./addCodeowners.ps1 -reponame "myRepo" -teamName "Developers"

Warning: When you make this call if you already have branch protection on it will fail. However if your PAT is an administrator or owner it will work as long as you don’t have Include Administrators set to true in your branch protection.

So if this is part of a larger script for setting up a repo. Just make sure this is run prior to setting up branch protection.

To take advantage of the CODEOWNERS file added to your repo be sure to turn that feature on in Branch Protection:

--

--

Dave Lloyd
ObjectSharp (a Centrilogic Company)

I have been writing software and teaching/coaching developers for 40 years. I love sharing knowledge and experience.