25 Jul 2016, 20:16

Auto Deploy Hugo to Github Pages

Want to know how to create a static website using Hugo and deploy it automatically using CircleCI to GitHub Pages? Everything free of charge? Read on!

This post covers exactly the same setup I’m using for this blog, so if TL;DR and you know your way around Hugo, you can jump directly to my repository.

Hugo is a static website generator. You choose a theme (or create your own), create the content using convinient Markdown format and call Hugo to generate your website. It produces HTML files along with statics ready to upload to your hosting provider’s server. Typical workflow looks like this:

$ hugo new site myblog && cd myblog
$ git clone https://github.com/dplesca/purehugo.git themes/purehugo # or other theme
$ edit config.toml # set theme
$ hugo new post/first-post.md
$ edit post/first-post.md
$ hugo -v

Now you should have your static website generated in a public directory.

Next we will setup GitHub Pages. First you need to create a repository called <username>.github.io. Everything that is inside will be publicly visible under http://<username>.github.io/. So if you create a hello world index.html there, it will work right away. If you want to have it under a custom domain, you only have to crate a CNAME record pointing at <username>.github.io and commit a CNAME file to your repository with your custom domain. You can check for example at my github pages repository.

Now the fun part: automation! We need two repositories. We already have <username>.github.io which is our destination. But we need a source for it, so let’s do git init in myblog directory we’ve created earlier with Hugo. We don’t want to commit build files inside the public directory, so let’s remove it and add it to .gitignore. Of course we also need to create that repository on GitHub, add a remote and push your files.

Now we have two public GitHub repositories (as our blog website is public anyway and we don’t have any secrets / DB credentials that should be hidden). This gives us possibility to also use a public CircleCI project that is free of charge. Our automation workflow will be as follows:

  1. Create a new blog post locally.
  2. Push changes to the myblog repository.
  3. CircleCI picks it up and runs hugo -v to generate static files.
  4. CircleCI pushes them to <username>.github.io repository.

CircleCI is configured by the circleci.yml file in root of the myblog repository. It installs Hugo on a build machine, clones the <username>.github.io repository to the public directory, runs hugo -v to generate static files and finally runs ci-deploy.sh that adds all new files generated by Hugo, commits them and pushes to the <username>.github.io repository.

There’s one more step to make it all work… CircleCI needs a write permission to the <username>.github.io repository. In order to do that, generate a new SSH key pair with ssh-keygen, add the public key as a deployment key to that repository and the private key to CircleCI under myblog project settings. It is called “SSH Permissions” and you should provide github.com as a hostname for that key.

You’re all set now. Commit changes to myblog repository and changes will appear on your website few minutes after. Everything based on free GitHub and CircleCI accounts!

16 Jul 2016, 13:54

Git Messages Again

When started this blog I was wondering what should be in the first post? Then I thought: what is a typical commit message of the first commit in a new repository? 90% of the times it says “Initial commit”. Well, starting a blog with “Initial Post” would be silly, so let’s talk about commit messages instead! What’s more, let’s talk about later commits, because the first one usually doesn’t really matter.

There are plenty of good blog posts about writing good commit messages already. I’ll just recap in short (but if it’s new to you, please check out the posts I’ve linked):

  1. A Subject, blank line, body format.
  2. Limit the subject to 50 characters, leave the period out.
  3. Use an imperative mood in the subject.
  4. Wrap the body at 72th column.
  5. In the body explain why, not how did you change something.

What’s really important is to understand why it all matters? Why bother with a lack of the period at the end of subject? Why bother with explaining why I fixed this simple bug, when the code is self explanatory? Nowadays teams and aprojects are getting bigger and bigger. If we compare lines of code from the past it’s obvious that projects are getting bigger and more developers work on them. And the bigger the team is, the more difficult it is to maintain the code. When the team is scaling out it is more important for developers to be good collaborators. And you can tell if a developer is a good collaborator by looking at his/her commit messages.

Another important factor is that a software deployment is tightly linked with SCM tools and workflows. It is popular to push on green (deploy from whatever commit in a master that passed all tests) or use git flow.

In the first scenario your software is deployed automatically by the CI when all the tests pass, so you might ask “why bother about commit messages?”. Well, if the tests don’t catch a bug that got deployed to a production, then you need to rollback. Good commit history will help you to identify where the problem might be. And in the situations when you have to rollback your production, you don’t want to analyze the code, because minutes or even seconds matter. You want to identify where the problem is as soon as possible.

If you’re using the git flow branching model, then it is also important to have a clean commit history with good messages, because you rely on that information when creating release branches, cherry-picking fixes, etc. Would you be confident deploying the release branch with an “important fix” commit without any more details?

Of course good commit messages is only one thing that helps with maintenance of a big project and a big team. There are other factors as keeping feature branches up to date using rebase, keeping a clean history by squashing minor commits, or splitting huge changes into multiple independent commits. More on that on this blog soon!