Skip to main content

Guide: Unraveling GitHub Actions - Detecting Changes Between Commits

While working at Hire Dragons, I was assigned the task of creating a GitHub Action workflow. This workflow was designed to use Laravel Pint to check for any changes in the codebase. On our local and off-site development machines, this task would take just a few moments. However, on GitHub, it would take 5-6 minutes to complete. Although you get many free Action minutes, we didn’t want to waste these credits on every commit. Therefore, I began exploring ways to speed up this process. During my research and development, I considered making a list of changes between commit hashes. This turned out to be the quickest method.

Let's start off with the code used

name: Lint
on:
  push
jobs:
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
          tools: phplint, laravel/pint
      - name: Get list of changed files
        id: getfile
        run: |
          changed_files=""

          if [[ "${{ github.event.before }}" == "0000000000000000000000000000000000000000" ]]; then
            git diff --name-status origin/development HEAD | grep -E '^[AM]\s+[^.]*\.php$' | awk '{print $2}' | xargs -I {} echo -n "{} " > changed_files_list.txt
          else
            git diff --name-status ${{ github.event.before }} ${{ github.event.after }} | grep -E '^[AM]\s+[^.]*\.php$' | awk '{print $2}' | xargs -I {} echo -n "{} " > changed_files_list.txt
          fi

          if [[ -s changed_files_list.txt ]]; then
            changed_files=$(cat changed_files_list.txt); echo "CHANGED_PHP_FILES=$changed_files" > $GITHUB_ENV
          else
            echo "No changed PHP files."
          fi

          rm -f changed_files_list.txt
      - name: Check syntax
        run: |
          if [[ ! -z "${CHANGED_PHP_FILES}" ]]; then
            phplint $CHANGED_PHP_FILES
          else
            echo "No PHP files have changed."
          fi
      - name: Check code style
        run: |
          if [[ ! -z "${CHANGED_PHP_FILES}" ]]; then
            pint -v --test $CHANGED_PHP_FILES
          else
            echo "No PHP files have changed."
          fi

This is the entire workflow and next we'll go over the breakdown.

1. Use the actions/checkout@v2: This action checks out your repository under $GITHUB_WORKSPACE, so your workflow can access it.

2. Setup the PHP environment with phplint and laravel/pint: These tools are prepared to check the syntax and style of your PHP files, ensuring they meet our coding standards.

3. Now we get to the secret sauce!

3a. First we set a variable to log the changed files (As the variable explains)

3b. In this part of the code, we look at a special case: the very first time code is pushed to a pull request. Here, we compare the latest code with the main development branch because there isn't a previous commit to compare with. We use git diff to find what's different in the new code (HEAD) from the development branch (origin/development). We're specifically looking for files that have been added (A) or modified (M) and end with .php. We list these files in a text document called changed_files_list.txt.

3c. If it's not the first commit, our task is simpler. We just compare the new changes (after) with the old ones (before). We use the same method to find and list the PHP files that have been changed.

3d. After listing potential changes, we check if our changed_files_list.txt is not empty, meaning there are changes. If it's empty, it means no PHP files have been changed, and we note that.

3e. Once we're done checking for changes, we don't need the list anymore, so we delete the changed_files_list.txt file to keep things tidy.

4. Check Syntax: Here, we use a tool called phplint to check if the PHP files that have changed are written correctly. This helps us find and fix any errors in the code that could prevent it from running properly.

5. Check Code Style: Lastly, we use Laravel Pint (pint), another tool, to ensure the PHP code style aligns with our team’s standards. This includes checking for formatting issues like spacing and brackets.

This breakdown explains each step of our workflow in simple terms. Next, we'll go over why each part is important and how it helps us work more efficiently.

Understanding the Impact of Efficiency

Q: Why do we make this change?
A: When using the free tier on GitHub, we are given 2,000 minutes to run Actions. This means if each Action takes 5-6 minutes, we can only run about 333 Actions in total. But if we can shorten each Action to just 2-3 minutes, we can run about 666 Actions. By doubling the number of Actions we can perform, we make the most of our resources without spending extra money.

How Efficiency Helps Us

Efficient use of resources is crucial, especially when working within limits like those provided by GitHub's free tier. By speeding up our Actions, we ensure that we can do more testing and make more updates to our projects, which leads to better software and happier users. Here’s how each part of our workflow contributes to this efficiency:

  1. Quick Setup: By setting up PHP and Laravel Pint right at the start, we ensure that every tool we need is ready to go immediately. This saves time every time we run the workflow.

  2. Smart Changes Detection: By only checking files that have changed, we avoid wasting time reviewing unchanged code. This not only speeds up the process but also means we use fewer minutes per Action.

  3. Effective Error and Style Checking: With `phplint` and `pint`, we catch errors and style issues early. This prevents problems down the line, which can be time-consuming and costly to fix later.

  4. Cleanup: Removing unnecessary files at the end of each run keeps our runs clean and tidy.

The Bigger Picture

By making our GitHub Actions more efficient, we're not just saving minutes; we're improving our overall workflow and productivity. These improvements mean we can push updates faster, fix bugs quickly, and deliver a better product to our users. Plus, staying within the free tier's limits helps keep project costs down, which is always a bonus for us and our stakeholders.

In conclusion, the changes we've implemented are about more than just speed—they enhance our development process, making it leaner and more cost-effective. This approach not only benefits us but also supports our commitment to delivering high-quality software efficiently and responsibly.

Comments

  1. This is my first ever blog post of many!
    *Inser "Initial commit" message joke here*

    ReplyDelete

Post a Comment

Popular posts from this blog

Guide: Unraveling GitHub Actions - Spend Less, Do More

How Can We Save Money & Increase Efficiency? To achieve this, we must find answers to specific questions. One challenge I faced was improving our test and lint workflows even further: "Although I have already enhanced the speed of our test and lint workflows, can I accelerate them more or reduce the costs associated with running them?" The answer came from a project I discovered during my R&D phase— nektos/act . This tool aims to perfectly mimic GitHub Actions, allowing you to make frequent updates and commits without needing to push each change to check if your tests or lints pass. Installing act I regularly use Ubuntu 22.04 on WSL2, and your setup might be different. Thus, this guide might not perfectly fit everyone's needs. For more detailed support, please visit the act homepage . First, install nektos/act using this command: curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/nektos/act/master/...

Open source: Simplifying the Ramp API

Why I Started This Project While working at Hire Dragons , I encountered a big challenge. There was a task that needed to be automated completely. Every day, someone would log into Ramp.com to handle routine tasks like checking upcoming shifts on our website and pre-filling a card using the Ramp service. This was their whole job because we have over 1,000 Dragons (users) possibly working shifts each day. How I Solved the Problem Initially, I looked into integrating a solution directly into our existing codebase. However, it seemed too complex and I thought, "Why not make this an open-source project?" Since the Ramp API is accessible to anyone with an account, I decided to share the fun with everyone! I created a project called "ramp-api" on GitHub to make using the Ramp API as easy as possible for developers. Getting Started with the Ramp API Package To use this package, first, you need to set up your configuration file. You can do this...