Bulk Update Github Branch Protection

By Rich

Wed Aug 04 2021

Recently I was faced with needing to update branch protection on over 75 Github repositories in an organisation. The repositories were created by multiple people over the last several years. Some had seperate development and production braches while others only had a production branch. The development branches were consistently named develop but the production branch was master in our older repositories and main in the newer ones.

While I could have manually updated each repository that was going to take time and I would need to remember to update each new repository. Luckily Github has an API these for things so I quickly resolved to set up a Lambda to handle this for me. The Lambda would be triggered once per day to clean up any repositories that had been created or changed.

import { Octokit } from "octokit";

// The name of the branches we want to protect
const PROTECTED_BRANCHES = ["develop", "main", "master"];

export const handler = async () => {
  // Get our organisation and auth from parameter store
  const { auth, org } = args;

  // Create an instance of the OctoKit SDK with our authentication
  const octokit = new Octokit({ auth });

  // Loop through all of the repositories in our organisation
  const repos = await octokit.rest.repos.listForOrg({ org, per_page: 100 });
  for (const repo of repos) {
    // Loop through all of the branches in each repository
    const branches = await octokit.rest.repos.listBranches({ owner: repo.owner?.login ?? org, repo: repo.name, per_page: 100 });
    for (const branch of branches) {
      // Is this a branch we want to protect?
      if (PROTECTED_BRANCHES.includes(b.name)) {
        // Update the branch protection
        await octokit.rest.repos.updateBranchProtection({
          headers: {
            accept: "application/vnd.github.luke-cage-preview+json",
          },
          branch: branch.name,
          enforce_admins: true,
          owner: repo.owner?.login || org,
          repo: repo.name,
          required_pull_request_reviews: {
            dismiss_stale_reviews: true,
            required_approving_review_count: 1,
          },
          allow_deletions: false,
          allow_force_pushes: false,
          required_conversation_resolution: true,
          required_status_checks: {
            strict: true,
            contexts: [],
          },
          restrictions: null,
        });
      }
    }
  }
};

When time permits I’ll look into triggering this via GitHub webooks

Want to learn more about serverless applications and devops with AWS?

Sign up for our newsletter.