Github Action Improvements
Intro
Two years ago, I added GitHub Actions to this site (in PR#47)! I’m the only developer here, but at the time I wanted to learn how to set up actions and add checks to keep myself honest on code quality.
This way my future self wouldn’t have to pay for my past self’s actions.
I’ve also enabled verified commits since then.
Why I did this
Since then I’ve learned more about writing actions. I wanted to apply what I’ve learned to refresh and improve the old ones. The old workflows were also getting outdated, cluttered, and difficult to maintain.
My goals
- Make tests clearer and easier to read.
- Skip unnecessary runs and avoid duplicates.
- Learn about composite actions to make scripts easier to read.
What changed
Before, formatting and linting actions were running all the time on every push and pull request. They ran even when unrelated files changed, so there was plenty of room for improvement.
What changed:
- Actions only run on push and skip if unrelated files changed.
- Concurrency stops duplicate actions and cancels old runs for quick follow-up updates.
- Composite actions simplify steps and I learned about reusable actions.
- Actions now have clear names like “Check linting” and “Check formatting” instead of generic ones.
Before and after
The new setup is easier to read and maintain, plus doesn’t run unnecessary checks. Here’s a summary of the main changes:
- Ignore changes to files that don’t affect tests.
- Add concurrency to cancel duplicate runs.
- Split the build, format, and lint steps into separate jobs.
- Use a composite action for setup.
Here’s the full diff to compare the before and after:
# .github/workflows/ci.yml
name: CI
# 1. Run on push to always test for issues.
- on: [push, pull_request]
# 2. Don't run if any of these unrelated files have changed.
+ on:
+ push:
+ paths-ignore:
+ - ".github/**"
+ - ".nvmrc"
+ - ".npmrc"
+ - ".gitignore"
+ - "public/**"
+
# 3. Add concurrency so that builds can be cancelled and there aren't duplicates.
+ concurrency:
# Make sure the same job isn't running.
+ group: ci-${{ github.ref }}
+ cancel-in-progress: true
jobs:
# 4. Replace generic `build` job since it wasn't accurate and was doing a lot more.
- build:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
- - name: Install packages
- run: npm i
- - name: Check linting
- run: npm run lint
- - name: Check formatting
- run: npm run prettier
# 5. Separate scripts into build, formatting, and linting tests.
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v5
# 6. Use a composite action to improve readability and avoid having to specify repetitive setup steps, like setting up and installing node.
+ - uses: ./.github/actions/setup
+ - name: Build site & styles
+ run: npm run build && npm run build:sass
+
+ format:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v5
+ - uses: ./.github/actions/setup
+ - name: Check formatting
+ run: npm run prettier
+
+ lint:
+ runs-on: ubuntu-latest
+ needs: format
+ steps:
+ - uses: actions/checkout@v5
+ - uses: ./.github/actions/setup
+ - name: Check linting
+ run: npm run lint
Highlights/results
Now, it’s much clearer on what each action does, unrelated changes don’t trigger tests, and the composite action saves two steps for setting up and installing node.
What I learned
Setting up composite actions were trickier than I expected. I wish the docs had more realistic examples. Still, it was worth the effort to add concurrency and composite actions.
Concurrency and ignoring unrelated files is something that I’ll look into more of my future scripts because that could save a lot of time and resources over time.
Conclusion
Updating the GitHub actions made them faster and easier to read. I learned a lot about composite actions and workflow performance.
I’ve added the final workflow below if you want to use it as a reference:
# .github/workflows/ci.yml
name: CI
on:
push:
paths-ignore:
- ".github/**"
- ".nvmrc"
- ".npmrc"
- ".gitignore"
- "public/**"
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: ./.github/actions/setup
- name: Build site & styles
run: npm run build && npm run build:sass
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: ./.github/actions/setup
- name: Check formatting
run: npm run prettier
lint:
runs-on: ubuntu-latest
needs: format
steps:
- uses: actions/checkout@v5
- uses: ./.github/actions/setup
- name: Check linting
run: npm run lint
You can also see it in the repository, here.