Before I rant about GitHub Actions, I'd like to set the context on where this dissatisfaction comes from. My team consists of about 15 engineers constantly pushing to the main branch. Our code lives in a monorepo split per module, which, through trunk based development, gets deployed multiple times a day.
I want to emphasize that your mileage may vary. There will be folks who say GitHub Actions are great (I also use them for smaller projects), but as with any tool, it has limits and might not be suitable for all problems. Let's look at some of them.
Our code sits in a monorepo which is further divided into folders. Every folder is independent of each other and can be tested, built, and deployed separately.
monorepo/
├─ api1/
├─ api2/
├─ web-app1/
├─ web-app2/
Each of these folders has its pipeline. We leverage GitHub Actions paths to trigger a pipeline only when there is a code change within that folder.
A good practice is not to allow pull requests to be merged unless all checks are green. However trivial it might sound, this becomes notoriously difficult with the above monorepo setup.
In GitHub you can specify a "required check", the name of the step in your pipeline that always has to be green before a pull request is merged. As an example, I can say that web-app1 - Unit tests
are required to pass. The problem is that this step will only run when I change something in the web-app1
folder. So if my pull request only made changes in api1
I will never be able to merge my pull request! 🤯
In these two GitHub threads 1, 2 you can see the impact. The bottom line is, that working around this limitation is hacky, difficult to maintain, and costly since you have to run additional pipelines just to determine if a pull request can be merged or not!
GitHub should not rely on specific names for the required checks. They can just say - all checks have to pass before you merge. That way, whatever pipelines and checks your pull requests have triggered will be considered mandatory. It's been almost 3 years since these issues were raised, and nothing changed yet!
My impression is that when your pipeline grows, it becomes more and more difficult to manage it with GitHub Actions. Here is an example workflow that can be called from other workflows, can be triggered manually, and triggers when someone pushes to the master branch.
name: CD - api1
on:
push:
paths:
- 'api1/**'
branches:
- master
workflow_dispatch:
inputs:
target_environment:
type: environment
default: 'staging'
required: true
workflow_call:
inputs:
target_environment:
type: string
required: true
jobs:
deploy-api1:
environment:
name: ${{ github.event_name == 'push' && 'production' || inputs.target_environment }}
smoke-tests:
if: ${{ github.event_name == 'push' || inputs.target_environment == 'production' }}
name: Smoke Tests
uses: ./.github/workflows/smoke-tests.yml
with:
target_environment: 'production'
secrets: inherit
What I notice doing more and more is that I have to add lots of if statements such as this.
if: ${{ github.event_name == 'push' || inputs.target_environment == 'production' }}
While I could split this into multiple workflows with different triggers, then I'm getting more and more files to maintain. A workflow reuse should be a one-liner but I always have to write more lines and a lot of duplicated statements such as workflow name, secrets: inherit
etc. Our .github
folder already contains 30+ files.
Another pitfall that happens often is the needs
clause. When you are refactoring and removing jobs, it's easy to forget to update this clause and subsequent steps. While there are linters available, they are not perfect. The sad part is that I can only see mistakes when I push the workflow, I'd expect to know about this way earlier.
needs: [ build, deploy, generate-release-tag ]
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/create-git-tag
with:
release_tag: ${{ needs.generate-release-tag.outputs.release_tag }}
It's a known thing that there is no way of running GitHub Actions locally. There is a tool called act but in my experience it's subpar.
Of all the pain points, this is the worst one. It seems that GitHub doesn't care about fixing any of these issues or improving its product. Some of the threads have been open for years without any action taken by GitHub. A lot of these issues have been recently closed by GitHub causing a backlash from the community. There are no signs that these will be addressed based on their public roadmap.
Considering all the problems listed, with the lack of motivation from GitHub I'd think twice before using GitHub Actions again. The CI/CD product space offers a lot of options such as Gitlab, Jenkins, TeamCity, etc. I used some of these and at this moment, they offer a better service for the money. Things like Dagger are also worth evaluating since they bring new perspectives into the game.