/BranchValidator

Validates branch names for the organization projects

Primary LanguageC#MIT LicenseMIT

BranchingDiagram BranchingDiagram

Branch Validator

Build PR Status Check Unit Test PR Status Check

Codecov

Good First GitHub Issues Discord

🤷🏼‍♂️ What is it? 🤷🏼‍♂️

This GitHub Action can be used to check whether or not GIT branch names are valid using an expression in combination with glob syntax. These expressions are functions that can be used in combination with && and || logic to perform the validation.

TLDR - Additional Information

What it really comes down to is enforcing branch names and structure. In CI/CD systems, the name of the branch can determine how the system runs. The workflows you have might depend on the name of a branch. For example, if the branch uses the GitHub issue number as part of the branch name, it will refer back to the GitHub issue. Your build may behave differently depending on which branch it is building.

When incorrect branch names are setup, they can cause issues with your build and release systems and confusion with your team. This GitHub action will help enforce project standards to help keep things running smoothly. For example, a branch name of my-branch does not express the purpose of the branch. Without enforcing naming conventions of branches, how is the team supposed to know the purpose of it? In addition, the ability to enforce an issue number to exist in the name of a branch, makes it easier for developers to find which branch belongs to which issue. With this kind of enforcement, you can setup automation to trust that the branch name contains a number. It also allows you to create automation to check if a GitHub issue exists, which would prevent incorrect issue numbers from being used in a branch name.

The applications of this GitHub action are endless!!

Note This GitHub action is built using C#/NET and runs in a docker container. If the job step for running this action is contained in a job that runs on Windows, you will need to move the step to a job that runs on Ubuntu. You can split up your jobs to fulfill runs-on requirements of the GitHub action. This can be accomplished by moving the step into its own job. You can then route the action step outputs to the job outputs and use them throughout the rest of your workflow.
For more information on step and job outputs, refer to the GitHub documentation links below:

🪧 Example 🪧

name: Branch Validation Sample Workflow

on:
  workflow_dispatch:

jobs:
  Validate_Branch:
    name: Validator Branch
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Validate Branch
      uses: KinsonDigital/BranchValidator@v1.0.0-preview.4 # Make sure this is the latest version
      with:
        branch-name: "${{ github.ref }}" # The current branch where the workflow is running.
        validation-logic: "equalTo('main')"
        trim-from-start: "refs/heads/"
        fail-when-not-valid: true # Optional. Default is true.

➡️ Action Inputs ⬅️

Input Name Description Required Default Value
branch-name The name of the GIT branch. yes N/A
validation-logic The expression used to validate the branch name. yes N/A
trim-from-start Trims the text from the beginning of a branch name. no empty
fail-when-not-valid Fails the job if the branch is not valid. no true

⬅️ Action Outputs ➡️

The name of the output is valid-branch and it returns a boolean of true or false. Click here to see an example of how to use the output of the action.


Validation Logic Expression Functions

Below is a small list of the available expression functions that you can use in the value of the validation-logic input. These expression functions can be used in combination with the && and || operators:

  • Example: equalTo('feature/my-*-branch') && allLowerCase()
    • This checks to see whether or not the branch is equal to the value and that the entire branch is lower case.
TLDR - Expression Function List
  1. equalTo(string) - Checks to see whether or not the given branch name is equal to the argument value of the function. The argument value must be a string value that is surrounded by single or double quotes. The quotes used must be the opposite of the quotes used for the entire input value. Standard YAML syntax rules apply. The function value allows the use of 2 characters that provide glob-like behavior. The 2 characters are # and * and can be used together as many times as needed.
    • Example 1: equalTo('main')
      • Checks whether or not the branch is equal to the value of main.
    • Example 2: equalTo('feature/my-*-branch')
      • Checks whether or not the branch starts with the value feature/my- and that it ends with -branch. Anything is acceptable between the beginning and end of the branch where the * character is located. This should be a familiar concept to other systems and uses of this type of syntax.
    • Example 3: equalTo('feature/#-sample-branch')
      • Returns valid if the branch name was feature/my-sample-branch. This checks whether or not the branch starts with the value feature/ and ends with the value -sample-branch. Any text between the start and the end will be checked to see if it is a whole number of any digit size.
        • Returns valid if the name of the branch was feature/12-sample-branch or feature/12345-sample-branch.
        • Return as not valid if the name of the branch was feature/10-20-sample-branch. In this example, the branch ends with the value -20-sample-branch, not -sample-branch.
    • Example 4: equalTo('release/v#.#.#-*.#')
      • Returns valid if the branch name was release/v1.2.3-preview.4.
  2. allLowerCase() - Checks whether or not the branch name is all lower case.
    • Example 1: allLowerCase()
      • Returns valid if the name of the branch was all-lower-case. This would return invalid if the name of the branch was not-all-LOWER-case.
  3. allUpperCase() - Checks whether or not if the branch name is all upper case.
    • Example 1: allUpperCase()
      • Returns valid if the name of the branch was ALL-UPPER-CASE. This would return invalid if the name of the branch was NOT-ALL-upper-CASE.

🪧 More Examples 🪧

The workflow fails when the feature branch does not start with the value feature/, followed by a number and a hyphen, ends with any text, and is all lower case:

name: Branch Validation Sample Workflow

on:
  workflow_dispatch:

jobs:
  Validate_Feature_Branch:
    name: Validate Feature Branch
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Validate Branch
      uses: KinsonDigital/BranchValidator@v1.0.0-preview.1
      with:
        branch-name: "feature/123-my-branch"
        validation-logic: "equalTo('feature/#-*') && allLowerCase()"
        fail-when-not-valid: true # Optional. Default is true.

Failing the workflow manually:

name: Branch Validation Sample Workflow

on:
  workflow_dispatch:

jobs:
  Validate_Feature_Branch:
    name: Validate Feature Branch
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Validate Branch
      id: validate-branch
      uses: KinsonDigital/BranchValidator@v1.0.0-preview.1
      with:
        branch-name: "release/v1.2.3-preview" # Missing the text '.4' at the end of the branch
        validation-logic: "equalTo('release/v#.#.#-preview.#')"
        fail-when-not-valid: false # This step will not fail the workflow

    - name: Fail Workflow # But this step will fail the workflow instead.
      if: ${{ steps.validate-branch.outputs.valid-branch }} = 'false'
      run: |
        Write-Host "::error::The branch is invalid!!";
        exit 1; # Fail the workflow

🙏🏼 Contributing 🙏🏼

Interested in contributing? If so, click here to learn how to contribute your time or here if you are interested in contributing your funds via one-time or recurring donation.

🔧 Maintainers 🔧

x-logo-dark-mode x-logo-light-mode Calvin Wilkinson (KinsonDigital GitHub Organization - Owner)

x-logo-dark-mode x-logo-light-mode Kristen Wilkinson (KinsonDigital GitHub Organization - Project Management, Documentation, Tester)


🚔 Licensing And Governance 🚔

Contributor Covenant GitHub

This software is distributed under the very permissive MIT license and all dependencies are distributed under MIT-compatible licenses. This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.