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:
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.
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.
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.
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.
This is my first ever blog post of many!
ReplyDelete*Inser "Initial commit" message joke here*