Dan Devins

Launching My New Site: A Git Push-to-Deploy Adventure

Today, I successfully launched my new website, built with the static site generator MkDocs, on my DreamHost server. Instead of manually uploading files with FTP, I wanted a more modern and efficient workflow. The goal was to create a "push-to-deploy" pipeline: when I push new changes to a Git repository on my server, the server should automatically build and publish the website.

This is the story of that journey, including the initial plan and the many troubleshooting steps it took to get everything working perfectly.

The Initial Plan: A 'Happy Path' to Deployment

The high-level plan was straightforward:

  1. Set up a Git Remote: Add a remote to my local Git repository that points to my DreamHost server via SSH.
  2. Create a Bare Repository on the Server: This special type of repository on the server would receive my pushes. It doesn't have a working copy of the files, just the Git history.
  3. Implement a post-receive Hook: This is a script that lives in the server's repository and runs automatically every time it receives a push.
  4. Write the Deployment Script Logic: The script would:
    • Check out the latest source code into a temporary directory.
    • Run mkdocs build to generate the static HTML files.
    • Copy the generated files from the site/ directory to my public web folder (dandevins.com).
  5. Push and Go Live: A simple git push from my local machine would trigger the whole process.

The Troubleshooting Journey: Debugging the Pipeline

As is often the case in development, the "happy path" had a few detours. Here is a breakdown of the issues we encountered and how we solved them.

Problem 1: git: command not found

The very first step failed. My local machine couldn't find the git command. This was a simple environment issue; Git wasn't installed or its location wasn't in my system's PATH variable. Once I installed it correctly, I was able to proceed.

Problem 2: fatal: You are on a branch yet to be born

After setting up the script and pushing for the first time, the deployment failed. The error message indicated that when the script tried to check out the files on the server, Git didn't know which branch to use. The initial git checkout -f command was too generic.

Problem 3: rsync: ... No such file or directory

The next push failed with an rsync error. The script was trying to copy the built files from the site/ directory, but that directory didn't exist. This meant the preceding mkdocs build command was failing silently.

Problem 4: mkdocs: command not found

The manual build revealed the root cause of the previous error: mkdocs wasn't installed on the server. On a shared host like DreamHost, you can't use system package managers like apt.

Problem 5: The Virtual Environment Saga

Creating a virtual environment hit its own snags (ensurepip is not available). This required consulting DreamHost's specific documentation to use their provided Python setup correctly. After that, we had to ensure the virtual environment was kept outside the public web directory for security.

Problem 6: The Final Boss - docs vs. Docs

The build was still failing, even with mkdocs installed. The error was now ERROR - Config value 'docs_dir': The path ... /docs' isn't an existing directory.

This was the most subtle problem, caused by a difference between my local Windows machine (case-insensitive) and the Linux server (case-sensitive).

  1. My local project folder was named Docs.
  2. mkdocs by default looks for a folder named docs (lowercase).
  3. My Windows machine and Git were getting confused. Even though I thought the folder was correct locally, Git's internal index still recorded it as Docs.

  4. Troubleshooting: We confirmed what Git was tracking using git ls-files, which showed Docs/index.md (uppercase).

  5. Solution: We had to force Git to recognize the case change with a two-step rename on my local machine: git mv Docs temp_folder, followed by git mv temp_folder docs.

Success!

After committing and pushing this final case-change fix, the deployment script ran flawlessly from top to bottom.

  1. The post-receive hook was triggered.
  2. The correct main branch was checked out.
  3. The Python virtual environment was activated.
  4. mkdocs build found the lowercase docs directory and successfully built the site.
  5. rsync copied the new files into /home/usr/dandevins.com.
  6. The website was live.

This journey was a fantastic learning experience. It highlighted the importance of robust scripting, understanding environment differences, and using targeted debugging to solve problems one by one. The final result is a clean, automated deployment pipeline that will make updating my site a breeze.


Back to Blog Index