Turning Pelican into a mini-CMS
Lowering writing inhibitions with tech
I like automating things. This means I write small nifty tools to do boring / repetitive stuff for me. I have been relying on static site generator Pelican for my website. I do go an extra mile from the usual workflow.
For this blog, I wanted to keep the source code and generated output
separate. A way to do that was to use git branches to develop
content and publish the output on the master
branch. While in theory
this sounds nice, it becomes cumbersome to manage two copies of the same
repository locally. The solution was CI.
Stage 1: CI
This very blog is automatically published on GitHub pages every time I
push some text to GitHub, specifically on the develop
branch. As a
result, I don’t have to remember to activate the Python virtual
environment, run a Makefile, commit output to another branch
(master
) etc.
I used to do this with Travis CI and ever since GitHub actions rolled out, I have been using the latter as it is noticeably faster. Snippets of the configuration files that I used are shown below.
Travis CI configuration
language: python ... install: - pip install -r requirements.txt - pelican-themes -i pelican-bluedrop/bluedrop script: - cd src - make publish deploy: provider: pages skip-cleanup: true github-token: "$GITHUB_TOKEN" keep-history: true target-branch: master name: Travis CI local-dir: "./output" on: branch: develop
An extra step you have to do is to generate a personal access token,
`GITHUB_TOKEN
<https://github.com/settings/tokens>`__ for Travis to
get permissions. Then, you save the token as a secret environment
variable in Travis. The process is nicely
documented.
GitHub actions workflow
name: Publish pelican website on: [push] env: PIP_CACHE_DIR: ~/.cache/pip jobs: build: runs-on: ubuntu-latest strategy: max-parallel: 4 matrix: python-version: [3.7] steps: - ... - name: Deploy to GitHub Pages if: success() env: ACTIONS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }} PUBLISH_BRANCH: master PUBLISH_DIR: ./output SCRIPT_MODE: true run: | wget https://raw.githubusercontent.com/peaceiris/actions-gh-pages/v2.5.0/entrypoint.sh bash ./entrypoint.sh
Here we use a third-party
action created to
deploy generated files to GitHub pages. We may not want to give too many
permissions here (i.e. access to all repositories as we did with
Travis!). Therefore a deploy key was generated from
https://github.com/<username>/<username>.github.io/settings/keys
instead.
Stage 2: Templating
Pelican posts require some metadata for the posts to be acceptable. Some (title, date) are mandatory while the rest are optional. I wanted the process of writing a new post to be as fluid as possible. I started by keeping a simple markdown file with dummy metadata. Then I would copy this file, and manually edit the metadata before authoring the post. As you can imagine, I was not pleased by this approach! Now I have come up with a better approach. The result was a Jinja template + interactive TUI workflow which creates a post stub, save it with the right filename, opens my editor, commits and pushes it! The template looks as follows:
{% block metadata -%} --- Title: {{ title }} Author: {{ author }} Date: {{ date }} Status: {{ status }} Summary: {{ summary }} Category: {{ category }} Tags: {{ tags | join(', ') }} --- {%- endblock %}
I did not want to build the TUI from the scratch. Therefore I borrowed
the prompt
module from the cookiecutter project
to do it for me. I save some defaults in a cookiecutter.json
file,
based on which the metadata values are prompted from the user
conveniently as follows:
title [Insert title]: Turning Pelican into a mini-CMS summary []: Lowering writing inhibitions with tech Select category: 1 - Blog 2 - Tech Talk Choose from 1, 2 [1]: 2 Select tags: 1 - life 2 - research 3 - software Choose from 1, 2, 3 [1]: 3 slug [turning-pelican-into-a-mini-cms]: pelican-mini-cms Select status: 1 - draft 2 - published Choose from 1, 2 [1]: 1 date [2020-01-02T14:12:41.803562]: author [Ashwin Vishnu Mohanan]: Select filetype: 1 - md 2 - ipynb Choose from 1, 2 [1]: Track changes? [True]: Commit changes? [True]: n Push changes? [False]:
The script which does this is self explanatory, I hope!
About the author
Ashwin Vishnu Mohanan, Ph.D. in Fluid mechanics