Preface

The motivation behind creating a custom GitHub Action for cleaning up branches. Here’s a breakdown:

  1. Reasons for creating the Action:
  • Specific need: There was a specific requirement for branch cleanup that existing actions couldn’t fulfill.
  • Exploration: The desire to experiment with GitHub Actions and explore what it can do.
  1. Problem with maintaining clean branches:

Team collaboration challenges: Encouraging team members to make branches clean consistently was found difficult. Multi-task development: developers usually have several tasks to do simultaneously, making it harder for codebase cleanup scarce. Neglected branch cleanup: Branch maintenance suffered because it was prioritized lower.

  1. Consequences of unclean branches:

Excessive number of irrelevant branches: Over time, many unnecessary branches accumulate. Search and management difficulties: The clutter made Finding and managing branches cumbersome.

  1. Solution and benefit:

Automated branch cleanup: A self-operating helper (GitHub Action) can clean up branches automatically, saving developers time. Benefits of automated cleanup: Improved organization, reduced merge conflicts, and better CI/CD performance.

First Step

You can check the final code here and how to use it. But please remember, this Action is not redoable; it will delete the branches that satisfy the criteria.

So far, Node.js is the most popular language on Github Action. It has an enriched ecosystem. This guide will use Node.js to show you how to develop your GitHub Action. We’ll also use Volta, a fancy, tiny, and efficient Node.js management tool, and act that can test Gihub Action end-to-end locally.

You can take a look at this post for more detail of volta。

  • Initionalize project folder
1
mkdir {your-project-path} && cd {your-project-path}
  • Initionalize project default value

This project use typescript, but we need it only in dev phase.

1
2
npm init
npm install --save-dev typescript @types/node @vercel/ncc @types/jest jest ts-jest gts

After installation, we can test whether it is successful via the command below:

npx tsc -v

After installing the packages, we need these packages initialized, like Typescript, gts, and jest.

There are various settings for initializing Typescript. You can reference here for more details and here for jest settings, for gts can check here.

There are tips for jest settings: do not use Typescript; just use a general javascript format. Otherwise, the compiler will check tsconfig.json’s rootDir to find jest.config.ts; if it cannot discover the file, it will throw an exception.

1
2
3
npx tsc --init
npx gts init
npx jest --init

You can install Typescript globally, although it’s convenient at first, but not so if you have a multi-version purpose.

1
2
3
# can install typescript globally, but not recommend
volta install typescript
tsc -v

After initializing these settings, we can set up the Nodejs version of the project. Now, we can use Volta to help us.

1
2
volta pin node@20.11.1
volta pin npm@10.4.0

By setting that so, Volta will automatically change the Nodejs and npm versions when we are in the folder.

Implement Customize Github Action

So far, our development environment is all set. Like a simple Nodejs project, we only need to implement the business logic afterward.

There are two valuable packages you will need to develop a GitHub Action:

1
2
npm update
npm install @actions/core @actions/github @octokit/plugin-rest-endpoint-methods

PS I install @octokit/plugin-rest-endpoint-methods this packages just because this Github Action need.

Set up Action Entrance

Github Action needs a file to explain this Action’s input/output, entrance, and execution environment (Nodejs, container, or others). And this key setting file is nether action.yml or Action.yaml file. You can check the details here.

Implement Action Logic

This action mainly uses Github rest API to fulfill the requirement.

Here are the four APIs we’ll use.

The process is simple, with just three steps:

  • Fetching the repo’s all branches except the protected branch & default branch.
  • Get the branch’s latest commit time.
  • If the latest commit time is over the threshold, check the force flag to decide whether to remove it.

Grant Action Permission

Because this Gitbhub Action will operate to a repo, we need to grant some permission to make it work. We can use fine-grained tokens, which Github provides. Remember, grant the minimum permission it needs. This action must delete branches when required, so make sure it has read-write on content. Check the details here.

About Testing

We all agree that the production code should be tested before it is shipped out, right?

We can test it if we want, check if logic can fulfill the requirements, and use jest to test business logic, just like in the Nodejs project. However, integrating with others’ actions is Github Action’s most powerful feature. Can we test in the local machine, not in a production environment? Project act gives us a solution.

This tool lets you test your GitHub Action and run it locally. By doing so, we no longer need to click here to there on the GitHub website.

Testing your Github Action Locally

Make sure you have installed docker before you use act. It does the same thing as aws-sam-cli; they pull down the image to run your action. The integration of other container solutions is poor; basically, it supports docker only; if you are not using docker like podman, it won’t promise work. You can check the official discussion.

How to use it

  1. Github action existing on Github.

For this example:branch-cleaner-action

  1. Create a target repo a workflow YAML file. act will use the settings in this YAML.

The workflow file is just like below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# C:\your_path\your_repo\.github\workflows\cleaner.yml
cleaner:
  runs-on: ubuntu-latest
  permissions:
    contents: write
  steps:
    - name: Clean Branches
      uses: RiceBen/branch-cleaner-action@v1.0.0
      with:
        secToken: ${{ secrets.GITHUB_TOKEN }}
        protect-branch-name: |
          main
          master          
        expiry-period-in-days: 5
        is-force-delete: true

We must provide secToken to this action, becuase this action will needs contents’s read-write permission.

The protect-branch-name is optional, it will skip the default branch of the repo avoid delete default branch. This behavior cannot chang.

  1. Open Terminal execute act ,debug with the fedback.

Here is the command we need on test:

act -W {your-workflow-full-path} -j {job-name-in-workflow} -s GITHUB_TOKEN="{your-git-hub-token}"

The act will execute all workflows and jobs by default. We can specify the job or workflow we want to test.

Reference