I've always loved the idea of automating stuff. And recently, I've created GitHub workflows that ran successfully, after hundreds of trials.
In the Frontend repo of Gitsecure, I had already included husky to help us catch Typescript errors before the build script runs and we deploy to Vercel. That sounds awesome, to be honest. And since then, we've been able to catch errors before we even commit them, leading to lesser build errors.
Take a look at the snippet below. It simply runs this — "prebuild-commit": "tsc --noEmit --incremental"
— command from our package.json
file
If you're trying to use Husky for the first time, consider going through their documentation
Drawbacks
For a while, this kept us going. But, there were limitations. One that was quite prevalent was the delay in committing a change. This particular issue affected me a lot because the PC I was using then was slow, and this factor impacted the duration of the checks.
Sometimes, I'd try committing a change, and my PC would just go off because of its poor battery. Normally, committing that change wouldn't take less than 5 seconds. But, since Husky is still running in the background, it takes a very long time.
This even led to a lot of complications for me. I remember a time I accidentally corrupted my git history. I couldn't perform any git operation, till I cleared it and started afresh.
So, now, imagine these types of frustrations when you have a large team with a handful of Engineers.
Enforcing a uniform code style
Although, the prettier extension on vscode does a good job of keeping all files formatted. But, we also have to consider cases where this extension isn't installed on the machine of someone on the team.
To avoid this, from the get-go, a prettier config had been included in the codebase, even before I started maintaining it. So, that's a good thing. To make prettier a part of our pre-commit process, I modified the format
command to do what the name implies — format the specified files.
I went ahead and modified the pre-commit file to accommodate the prettier rules. It became this:
I soon ran into an error. Every time the pre-commit hook runs, prettier formats all the files, excluding those in .prettierignore
. Whenever it encounters any file that doesn't match the presets, it makes those changes.
But Git isn't aware of those changes. So we'd end up making a commit and creating new changes. Two things led to this:
-
The execution order of the commands in
.husky/pre-commit
was wrong in this context. The prebuild script runs before formatting which shouldn't be so. What we want is to format our files, and then check for TS errors. -
Even at that, git still isn't aware of the changes we just made. To fix that, I modified the command like so:
To make everything more uniform, I included a .editorconfig
file with rules guiding how code is authored in the codebase. Now we're good to go!
Automating this process
As I mentioned earlier. This process can be sometimes slow for other people who might be in the same situation I was in. And to even improve the experience of devs on the team, it is better to move this process into a CI environment.
Fortunately, this project resides on GitHub, which means we have access to Actions. But, before doing that, I knew that Husky works in a local first context, and I had no idea how to go about moving this check into a Action.
But, I read somewhere that GitHub attaches a $CI
variable to actions or scripts running in a Continuous Integration environment. With this, I went on to modify the pre-commit file to run based on that condition with the Bourne shell syntax.
With this, the check will only run in a CI environment, a GitHub Action in our case.
Now, that this is settled. I went ahead to create a workflow in the ./github/workflows/
directory like so with one job including its required steps like so:
The workflow will only be triggered when there's a pull request to the main
or dev
branches. The important part of the pre-build-checks
job is the "Compile for errors" steps. Notice how it runs the script in the .husky
directory.
Disabling Vercel's auto-deploy
One thing I noticed after getting the pre-commit workflow to run was that the Vercel build ran without the context of this workflow. So even if, and when the checks pass or fail, the auto-deploy from Vercel still runs, nonetheless.
That's not what I want. So I headed to Vercel's doc and found out that we can disable the auto-deploy by setting a config in the vercel.json
file. See what it looks like below:
Yes, you can also selectively disable auto-deploy for different branches. More on that here
Managing deployments with a GitHub Action
With that out of the way. I had to figure out how to take control of the deployment process with a workflow since my original plan was to make sure this build was dependent on the completion of the pre-commit
checks.
This guide from David Myers was super helpful in setting up a vercel deployment with Actions. You should give it a read.
When I went through the guide, I found out that his examples were not hinged on the completion status of another workflow. His were dependent on workflow_dispatch
and pull_request
events.
To implement what I wanted, I had to use the workflow_run
to watch for the completion of the pre-commit-check
workflow by passing its name and setting its type to completed
.
So my workflow file became this:
You can learn more about events that trigger workflows here
What's next?
Well... I too, do not know. But, I'm pleased at the idea of not having to do this on my PC again. It is the problem of Actions now.