Skip to content

Blog

Bisecting bugs with binary search

The problem

A couple of days ago while working on my blog, I found out that the full-text site search didn’t work anymore. On the desktop, I couldn’t see the search UI at all as seen in the following screenshot.

Desktop search UI missing

And mobile search UI looked pretty strange with two search inputs…

Two search input in mobile view...

Something was wrong and I needed to get to the bottom of it. At the time I noticed the issue I was setting up astro-compress to compress static assets after the build. I thought maybe something went wrong during the compression so I tried excluding pagefind (Starlight uses Pagefind to implement full-text site search):

astro.config.mjs
import compress from "astro-compress";
export default defineConfig({
integrations: [
compress({
Exclude: [(file) => file.includes("pagefind")],
}),
],
});

Neither excluding these assets nor disabling the compression altogether helped. It was high time to turn to git bisect for help.

Bisecting the bug with Git

git bisect is (obviously) a git command that uses binary search to find the commit that introduced a bug. It does so by asking for good and bad commits and once these commits are identified it starts halving the commits between these until the commit that introduced the bug is found.

Locating and fixing the bug

I knew that the latest commit had the bug so it was time to start the bisecting process so I ran the following command in the terminal:

Terminal window
git bisect start

Here is the output of the command:

Terminal window
bugron.github.io git:(test) git bisect start
status: waiting for both good and bad commits
bugron.github.io git:(test) git bisect bad
status: waiting for good commit(s), bad commit known

Notice there is no need to mark the very first commit as bad when starting to bisect as git bisect start already assumes that the current commit is bad. All I needed was to find a good commit and to do that I went back to the last known good commit (by git checkouting older commits and checking for the existence of the bug) and ran git bisect good:

Terminal window
bugron.github.io git:(test) git checkout 69da06aa1c9e2d620ac3ebba25ddf956c31d8cf5
Note: switching to '69da06aa1c9e2d620ac3ebba25ddf956c31d8cf5'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at 69da06a Add light and dark logo variations
bugron.github.io git:(69da06a) git bisect good
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[d1eef597555defb5c235013142a42c82fed8120b] Add lastUpdated config

As you can see above I’ve git checkouted to the 69da06aa1c9e2d620ac3ebba25ddf956c31d8cf5 commit and as it did not contain the bug I marked it as a good commit with git bisect good. Git immediately started the bisection process by checking out the d1eef597555defb5c235013142a42c82fed8120b commit and even showing a rough estimation of the number of remaining steps.

From now on here is the algorithm I followed:

1. Check if a commit contains the bug
2. If it does mark it bad with `git bisect bad`
3. If it does not mark it good with `git bisect good`
4. Repeat steps 1-3 until the commit that introduced the bug is found

After a few iterations as the final step git presented me with the following commit:

Terminal window
bugron.github.io git:(fc71196) git bisect good
fb05597e11b01673c133b977542c9360b9ad2619 is the first bad commit
commit fb05597e11b01673c133b977542c9360b9ad2619
Author: Arsen Melikyan <bugron@mail.ru>
Date: Sun Jan 7 19:41:24 2024 +0400
Enhance current header for mobile experience
astro.config.mjs | 3 +-
src/components/Header.astro | 126 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 128 insertions(+), 1 deletion(-)
create mode 100644 src/components/Header.astro

Interesting. The Enhance current header for mobile experience commit is exactly where I made some changes to the header component but I didn’t change the search functionality at all. Or so I thought…

OK, let’s see what this bad commit did with git show fb05597e11b01673c133b977542c9360b9ad2619. For the sake of brevity I won’t show the whole output of the command but here is the relevant part:

git show fb05597e11b01673c133b977542c9360b9ad2619
diff --git a/src/components/Header.astro b/src/components/Header.astro
new file mode 100644
index 0000000..aaed8ae
--- /dev/null
+++ b/src/components/Header.astro
+<div class="header sl-flex">
+ <div class="sl-flex">
+ <SiteTitle {...Astro.props} />
+ </div>
+ <div class="sl-flex right-group md:sl-hidden">
+ <div class="search">
+ <Search {...Astro.props} />
+ </div>
+ <div class="blog-link">
+ <a href="/blog">Blog</a>
+ </div>
+ <LanguageSelect {...Astro.props} />
+ </div>
+ <div class="sl-hidden md:sl-flex">
+ <Search {...Astro.props} />
+ </div>
+ <div class="sl-hidden md:sl-flex right-group">
+ <div class="sl-flex social-icons">
+ <SocialIcons {...Astro.props} />
+ </div>
+ <div class="blog-link">
+ <a href="/blog">Blog</a>
+ </div>
+ <ThemeSelect {...Astro.props} />
+ <LanguageSelect {...Astro.props} />
+ </div>
+</div>

Hmm, at this moment all I had were assumptions but one thing I saw was I had two “instances” of <Search /> (remember the mobile search UI had two search inputs?) one of them should only be visible in mobile view the other one in desktop view.

I mistakenly thought that it would be OK to do this and then just use CSS to control the visibility of the search UI but Starlight had another idea so I attempted to remove the second instance of <Search /> and that fixed the issue. Afterwards, I simply polished the UI and committed my changes. Everything worked as expected and I deployed my changes 🚀

Conclusion

git bisect is an incredibly powerful tool in the git arsenal for finding bugs if git is used correctly. It takes some discipline and practice to keep commits atomic and small but it’s worth it in the long run. I highly recommend using it.

I hope you found this article useful. Until next time 👋

Astro, Starlight and GitHub Pages: How to quickly setup a blog

I’ve been delaying setting up my personal blog for so long that a few days ago I finally decided to do something about it 😅 And I’m glad I did because I finally got my hands dirty with Astro and Starlight for the first time.

If you’re interested in following my journey I invite you to read this article.

Used technologies

Here is the list of tech I used to create this blog:

  • Astro - “a web framework for content-driven websites”
  • Starlight - an Astro template for building documentation websites
  • GitHub Pages - a static site hosting service that takes HTML, CSS, and JavaScript files straight from a repository on GitHub. Conveniently, GitHub Pages supports custom domains, HTTPS, etc. and comes included in any GitHub plan.
  • GitHub Actions - a CI/CD tool that helps you automate your software development workflows
  • Google Analytics - a web analytics service offered by Google that tracks and reports website traffic

Astro

Astro is a modern web framework that allows you to build faster websites with less client-side JavaScript. It takes content from anywhere (Markdown, MDX, CMS, etc.) and turns it into blogs, static sites, even web apps. Since Markdown and MDX files are supported by Astro out of box that’s what I decided to use as the “content layer” for my blog.

It’s very easy to start a new Astro project with their CLI:

npm create astro@latest

Starlight

Instead of vanilla Astro I opted in using Starlight that is an official “wrapper” on top of it for building documentation websites (similar to Docusaurus and others). Interestingly, Starlight is just a template for Astro that you can install with the same Astro CLI:

npm create astro@latest -- --template starlight

I also found out that starlight-blog package seamlessly adds blogging capabilities. Starlight’s stellar (pun intended) features like i18n, full-text site search, visual mode switch, and many more are all supported out of box. That meant less work for me to get the blog going so I was sold right away.

starlight-blog actually required some more work to get it running with latest Astro versions, but everything seems to function nicely so far.

BTW I used Starlight’s theme editor to customize the colors of my blog. It’s pretty neat.

GitHub Pages

I decided to go with GitHub Pages as a hosting provider for the blog because it’s easy to setup and maintain, and it supports custom domains and HTTPS. I also use GitHub for my code so it was a natural choice for me.

I’ve never used custom domains with GitHub Pages before so I had to do some research. I found this article in GitHub docs that explains how to do it. It’s pretty straightforward.

Next, I added public/CNAME with the melikyan.dev domain name to bugron.github.io repository as per Astro documentation.

My domain’s DNS records needed an update too so that GitHub could recognize it. I use Porkbun for my domains and they have a guide on how to configure custom domains with GitHub Pages as well. Sweet.

In case you’re asking why Porkbun not only they provide good service they’re also fun. Just look at this “warning” (you can find it in the footer of their pages) 😂

Porkbun's "warning" :)

As I previously had something deployed to bugron.github.io from the main branch and I wanted to use GitHub Actions to deploy my blog I had to change the source in GitHub Pages to GitHub Actions.

Additionally, I updated the deployment branch rule of github-pages environment (you can find environments in repository settings, Environments under the Code and automation section) to point to the new astro branch otherwise the deployment simply wouldn’t happen 🤷‍♂️

Now we’re all set to actually deploy our blog to GitHub Pages.

GitHub Actions

Astro conveniently provides a guide on how to deploy an Astro static site to GitHub Pages using GitHub Actions.

Now for the lastUpdated configuration to work as expected we want to fetch the whole git history so we need to slightly modify the provided workflow:

.github/workflows/deploy.yml
name: Deploy Astro blog to GitHub Pages
on:
# Trigger the workflow every time you push to the `main` branch
# Using a different branch name? Replace `main` with your branch’s name
push:
branches: [astro]
# Allows you to run this workflow manually from the Actions tab on GitHub.
workflow_dispatch:
# Allow this job to clone the repo and create a page deployment
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Only a single commit is fetched by default, for the ref/SHA that triggered the workflow. Set fetch-depth: 0 to fetch all history for all branches and tags
- name: Install, build, and upload your site
uses: withastro/action@v1
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1

After adding the deployment workflow file I committed it to the astro branch and pushed it to GitHub. The workflow started automatically and after a a minute or so my blog was live at melikyan.dev.

melikyan.dev was deployed successfully

It’s time to publish some articles 🚀

Conclusion

And that’s it! No, I did not forget about Google Analytics but so much had been said about how to integrate it into websites that I don’t think we need another guide for it 😉

Now you know how to quickly setup a blog with Astro, Starlight, and GitHub Pages. I hope this article was helpful. Until next time!