As of yesterday, this blog is automatically being published via Travis CI. When I push a new commit to my GitHub repository it triggers a new build in Travis CI. The build completes and the the git repository is then updated with the generated output (mostly HTML with some static CSS).
The overall flow looks as follows:
This is how I set it all up.
Please see issue issue.
Blog repository setup
I use pelican as my blog engine. The “source” code for my
blog lives at the amitsaha.github.io
site branch. Besides the content (markdown and restructured text files) and
pelican specific files, the important files related to publishing are:
Dockerfile is used in Travis for building the site and is as follows:
RUN apt-get update && apt-get -y install python3-pip make bash git
RUN pip3 install pelican pelican-youtube markdown pelican-gist
RUN git clone https://github.com/gfidente/pelican-svbhack /tmp/pelican-svbhack
RUN git clone --recursive https://github.com/getpelican/pelican-plugins /tmp/pelican-plugins
ENTRYPOINT ["make", "build"]
Makefile has a number of targets, but only the
build target is currently being used:
$(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(PUBLISHCONF) $(PELICANOPTS)
cp 404.md $(OUTPUTDIR)/
The first command generates the site and places the generated files in the
output sub-directory. In addition
we also copy the
404.md file to the
output directory to serve a
custom 404 page.
The contents of the
output sub-directory is what we copy to the
master branch. This is
done via Travis CI via the instructions in the
To summarize, my blog has two branches:
site: “source” for the blog and other files necessary for generating the HTML for the blog
master: The generated HTML files live in this branch
The generation step is done via Travis and the generated files are pushed to the
Generating the blog
.travis.yml file is read by Travis CI and is the entry point for what happens when we push a
commit to the
site branch of the repository. Below I reproduce snippets from the file and their
The blog source is in the site branch so we want to only build when a push has been made to that branch:
We also don’t bother cloning more than the last commit (Learn more).
Next, we configure the language and specify that we want to use docker:
generic language ensures that our
.travis.yml completely controls what commands are run
as part of our build.
docker to carry out the build and generation. To do so, we have to specify the following:
(To learn more about docker in Travis CI, see this)
We then specify the
install steps. The
before_install step builds
the docker image:
- docker build -t amitsaha/pelican .
install step then creates a container from the image we just built:
- docker run -v `pwd`:/site -t amitsaha/pelican
install step runs a container which populates the
output sub-directory with the generated
The remaining step is to tell Travis CI’s GitHub pages “deployer” to deploy the generated output files:
github_token: $GITHUB_TOKEN # Set in travis-ci.org dashboard
We we will learn how we set the environment variable,
GITHUB_TOKEN in a later section.
We basically tell travis CI that we want the build to be done on the
site branch and the generated
files from the
local_dir directory to be pushed to the
target_branch which is
fqdn to the custom domain updates the repository settings in GitHub and also adds
a CNAME file in the master branch (Learn more). Please see documentation on how to setup a custom domain from scratch.
Adding the repository to Travis CI
We will then login to Travis CI and follow the guide
to add our repository. Under the hood, this step adds a new service integration to our repository. We can see the
If you are logging in for the first time using GitHub (or signing up), you will be presented with the following:
Travis CI repository settings
Next, we will configure the repository settings in Travis to add the
variable and set the value to a generated a personal access token. You can generate one by going to
https://github.com/settings/tokens and giving it only the
Hope you find the post useful. I reverse engineered this process after having already done all the setup, so I may have missed something. Please let me know (link below).